package com.googlecode.cnasort.cc.rmi.server.core;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.rmi.RemoteException;
import org.apache.log4j.Logger;
import com.googlecode.cnasort.cc.rmi.common.RMIFileImpl;
import com.googlecode.cnasort.cc.rmi.common.RMIFileLoaderConnectorV0;
import com.googlecode.cnasort.cc.rmi.common.data.RMIDirectory;
import com.googlecode.cnasort.cc.rmi.common.data.RMIFile;
import com.googlecode.cnasort.cc.rmi.common.data.impl.RMIDirectoryImpl;

/**
 * Default implementation of {@link RMIFileLoaderConnector}
 */
public class RMIFileLoaderConnectorV0Impl implements RMIFileLoaderConnectorV0, Serializable
{
    private static final long serialVersionUID = 5624806831442597663L;
    //private static final Logger logger = Logger.getLogger( RMIFileLoaderConnectorV0Impl.class );
    private Message logger = new Log4JMessage( Logger.getLogger( RMIFileLoaderConnectorV0Impl.class ) );

    protected RMIFileLoaderConnectorV0Impl() throws RemoteException
    {
    }

    public void setMessage( Message logger )
    {
    	this.logger = logger;
    }
    
    public static RMIFileLoaderConnectorV0Impl createRemote() throws RemoteException
    {
    	RMIFileLoaderConnectorV0Impl instance = new RMIFileLoaderConnectorV0Impl();

        //instance.serviceName = serviceName;

        return instance;
    }

    @Override
    public boolean connect() throws RemoteException
    {
        return true;
    }

    @Override
    public void disconnect() throws RemoteException
    {
    }

    @Override
    public RMIDirectory[] getRootDirectories()
        throws RemoteException
    {
        logger.info( "[S] received getRootDirectories()" );

        //return getRootDirectories();
        if( logger.isTraceEnabled() ) {
            logger.trace("[S] getRootDirectories() called" );
            }

        File[] roots = File.listRoots();

        if( roots == null ) {
            return new RMIDirectory[ 0 ];
            }

        RMIDirectory[] dirs  = new RMIDirectory[ roots.length ];

        for( int i = 0; i<roots.length; i++ ) {
            dirs[ i ] = new RMIDirectoryImpl( roots[ i ] );
            }

        return dirs;
    }

    @Override
    public RMIDirectory[] getDirectories(
        final RMIDirectory    directory
        ) throws RemoteException
    {
        //return getDirectories( directory );
        File[] files = directory.getPath().toFile().listFiles( new FileFilter() {
            @Override
            public boolean accept(File pathname)
            {
                return pathname.isDirectory();
            }} );

        if( files == null ) {
            return new RMIDirectory[ 0 ];
            }

        RMIDirectory[] dirs  = new RMIDirectory[ files.length ];

        for( int i = 0; i<files.length; i++ ) {
            dirs[ i ] = new RMIDirectoryImpl( files[ i ] );
            }

        return dirs;
    }

    @Override
    public RMIFile[] getFiles(
        final RMIDirectory    directory
        ) throws RemoteException
    {
        //return getFiles( directory );
        File[] files = directory.getPath().toFile().listFiles( new FileFilter() {
            @Override
            public boolean accept(File pathname)
            {
                return !pathname.isDirectory();
            }} );

        if( files == null ) {
            return new RMIFile[ 0 ];
            }

        RMIFile[] fs  = new RMIFile[ files.length ];

        for( int i = 0; i<files.length; i++ ) {
            fs[ i ] = new RMIFileImpl( files[ i ] );
            }

        return fs;
    }

    @Override
    public byte[] getFileContent(
        final RMIFile file
        ) throws RemoteException
    {
        //return getFileContent( file );
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        if( logger.isTraceEnabled() ) {
            logger.trace("[S] getFileContent(" + file + ") called" );
            }

        try {
            InputStream fi  = new FileInputStream( file.getPath().toFile() );

            try {
                byte[] buffer = new byte[1024];
                int    len;

                while( (len = fi.read( buffer )) >= 0 ) {
                    out.write(buffer, 0, len);
                    }
                }
            finally {
                fi.close();
                }
            }
        catch (IOException e) {
            RemoteException ne = new RemoteException( "getFileContent(" + file + ")" );
            ne.initCause( e );
            throw ne;
            }

        return out.toByteArray();
    }

    @Override
    public void quit() throws RemoteException
    {
        logger.info( "[S] received quit()" );

        // FIXME RMIFileLoaderConnectorHelper.quit( this, this.serviceName );
    }
}
